﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.Net;

namespace BerkelyAlgorithem2
{
    public partial class MasterForm : Form
    {
        RunningClock c;
        public NeighbourTable Neighbours;
        System.Threading.Thread t;
        System.Threading.Thread t2;
        Master m;
        int offsetCounter;
        int bestOffset;
        int worstOffset;

        
        public MasterForm(NeighbourTable N, Form1 f)
        {
            InitializeComponent();
            this.Neighbours = N;
            CheckForIllegalCrossThreadCalls = false;
            c = new RunningClock();
            t = new Thread(mainn);
            t2 = new Thread(formLabelUpdater);

            offsetCounter = 0;
            bestOffset = 0;
            worstOffset = 0;

            c.run();
            t.Start();
            t2.Start();
            f.Visible = false;
            this.button4.Enabled = false ;
        }

        public void formLabelUpdater()
        {
            int sumOfOffsets = 0;
            int numberOfUpDates = 0;

            if(m!=null)
                this.Grid.Rows.Add(m.Neighbours.Neighbours.Count);

            while (true)
            {
                //System.Threading.Thread.Sleep(8);
                int i = 0;
                if (offsetCounter == 50)//update one in 50 loops of while
                {
                    try
                    {
                        this.label1.Text = utils.DateTimeAsString(c.CurrentTime);
                    }
                    catch
                    {
                        Environment.Exit(0);
                    }

                    if (m != null)
                    {
                        if (numberOfUpDates != 0)
                        {
                            this.label2.Text = "running offset avarage is";
                            this.label3.Text = (Math.Abs(sumOfOffsets) / numberOfUpDates).ToString();
                        }

                        //update DataGridView

                        this.Grid.RowCount = m.Neighbours.Neighbours.Count;

                        foreach(Neighbour n in m.Neighbours.Neighbours)
                        {
                            sumOfOffsets += n.offset;
                            numberOfUpDates++;

                            this.Grid[0, i].Value = n.Address.ToString();
                            this.Grid[1, i].Value = n.IsAlive.ToString();
                            this.Grid[2, i].Value = n.offset.ToString();
                            //this.Grid[3, i].Value = n.offset.ToString();
                            
                            //color the cells red
                            if (n.nupa || n.nupaCounter >= 10)
                            {
                                this.Grid[0, i].Style.BackColor = Color.Red;

                            }
                            else
                            {
                                this.Grid[0, i].Style.BackColor = Color.White;
                            }

                            i++;

                        }
                    }

                    offsetCounter = 0;
                }
                else
                {
                    offsetCounter++;
                }
                if (m != null)
                {
                    if (m.masterNupaTooMuch)
                    {
                        //incase master was nupa 10 times or more
                        masterSiftedLabel.Visible = true;
                    }
                    else
                    {
                        masterSiftedLabel.Visible = false;
                    }
                }
                    
            }
        }

        ~MasterForm()
        {
            System.GC.Collect();
            GC.WaitForPendingFinalizers();

            if (t != null)
            {
                if (t.IsAlive)
                {
                    try
                    {
                        t.Abort();
                    }
                    catch
                    {

                    }
                }
            }

            if (t2 != null)
            {
                if (t2.IsAlive)
                {
                    try
                    {
                        t2.Abort();
                    }
                    catch
                    {

                    }
                }
            }

            this.Dispose();
            System.GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        public void mainn()
        {

            Console.WriteLine("the local NeighbourTable is:");

            int i = 0;
            Neighbours.iterationNumber += 2 * Neighbours.Neighbours.Count;
            foreach (Neighbour n in Neighbours.Neighbours)
            {
                n.syncPort = 9000 +Neighbours.iterationNumber + i;
                Console.WriteLine(n.Address + ":" + n.syncPort);
                i++;
            }

            m = new Master(Neighbours, c);
            Console.WriteLine("invoking Master.Start()");

            while (true)
            {
                m.start();
            }
        }

        //add 1 sec
        private void button1_Click(object sender, EventArgs e)
        {
            c.setTime(1000);
        }
        //sub 1 sec
        private void button2_Click(object sender, EventArgs e)
        {
            c.CurrentTime.AddMilliseconds(-1000);
        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);

            if (e.CloseReason == CloseReason.WindowsShutDown) return;

            // Confirm user wants to close
            switch (MessageBox.Show(this, "Are you sure you want to close?", "Closing", MessageBoxButtons.YesNo))
            {
                case DialogResult.No:
                    e.Cancel = true;
                    break;
                default:
                    break;
            }

            if (t != null)
            {
                if (t.IsAlive)
                {
                    try
                    {
                        t.Abort();
                    }
                    catch
                    {

                    }
                }
            }

            if (t2 != null)
            {
                if (t2.IsAlive)
                {
                    try
                    {
                        t2.Abort();
                    }
                    catch
                    {

                    }
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        private void CutoffMethod_Click(object sender, EventArgs e)
        {
            if (m != null)
            {
                if (m.cutoff_method == 0)
                {
                    m.cutoff_method = 1;
                    this.percent.Visible = true;
                    this.CutoffMethod.Text = "Change to Cutoff By MS";
                    this.label13.Text = "Set To:";
                    this.textBox1.Text = (m.percent_Cutoff * 100).ToString();
                }
                else
                {
                    m.cutoff_method = 0;
                    this.percent.Visible = false;
                    this.CutoffMethod.Text = "Change to Absolut Cutoff By Percent";
                    this.label13.Text = "Cutoff in MS:";
                    this.textBox1.Text = m.cutoff.ToString();
                }
            }
        }

        private void Submit_Click(object sender, EventArgs e)
        {
            if (m != null)
            {
                if (this.textBox1.Text != null && this.textBox1.Text.Length != 0)
                {
                    int intTest;
                    bool isNum = int.TryParse(textBox1.Text, out intTest);
                    if (isNum)
                    {
                        if (m.cutoff_method == 0)
                        {
                            m.cutoff = intTest;
                        }
                        else
                        {
                            m.percent_Cutoff = intTest / 100;
                        }

                    }
                    else
                    {
                        MessageBox.Show("Must enter a number...");
                        this.textBox1.Text = "";
                    }
                }
            }
        }

        private void timeToTake_Click(object sender, EventArgs e)
        {
            
            if (m != null)
            {
                if (m.allNupuSelection == 0)
                {
                    m.allNupuSelection = 1;
                    timeToTake.Text = "Switch To: Take the Master's Time";
                    this.siftStatus.Text = "Take The Avarage of all";
                }
                else
                {
                    m.allNupuSelection = 0;
                    timeToTake.Text = "Switch To: Take The Avarage of all";
                    this.siftStatus.Text = "Take the Master's Time";
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            //if (m != null)
            //{
            //    this.m.optimized_mode_flag = 1;
            //}
            //this.button3.Enabled = false;
            //this.button4.Enabled = true;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            //if (m != null)
            //{
            //    this.m.optimized_mode_flag = 0;
            //}
            //this.button4.Enabled = false;
            //this.button3.Enabled = true;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (m != null)
            {
                m.timeBetweenSync = int.Parse(this.timeBetween.Text);
            }
        }
    }

}
